package org.dromara.one.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Component
public class LogFileConfig {
    //初始化
    public  String init(String url,String sqlFileName){
        File file = new File(url);
        if(!file.exists()){//如果文件夹不存在
            file.mkdir();//创建文件夹
        }
        String skylampLastFileUrlTemp = url + "/" + sqlFileName;
        File f = new File(skylampLastFileUrlTemp);
        if (!f.exists()){
            try {
                f.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return skylampLastFileUrlTemp;
    }

    public  void save(String url,String data){
        File file = new File(url);
        List<String> list = FileUtil.readLines(file, "utf-8");
        list.add(data);
        FileUtil.writeUtf8Lines(list,file);
    }

    public  void saveLock(String url,String data){
        FileChannel fileChannel = null;
        FileChannel tempFileChannel = null;
        FileLock fileLock = null;
        RandomAccessFile raf = null;
        try {
            tempFileChannel = new FileOutputStream(url, true).getChannel();
            raf = new RandomAccessFile(url,"rw");
            raf.seek(raf.length());
            fileChannel = raf.getChannel();
            fileLock = fileChannel.lock();
            ByteBuffer byteBuffer = ByteBuffer.wrap((data + "\n").getBytes(StandardCharsets.UTF_8));
            fileChannel.write(byteBuffer);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            closeAll( fileChannel, tempFileChannel, fileLock, raf);
        }
    }

    public List<String> read(String url, boolean isCopy,File file1,String sqlFileUrl){
        FileChannel fileChannel = null;
        FileChannel tempFileChannel = null;
        FileLock fileLock = null;
        RandomAccessFile raf = null;
        StringBuffer sb = new StringBuffer();
        List<String> list = new ArrayList<>();
        try {
            tempFileChannel = new FileOutputStream(url, true).getChannel();
            raf = new RandomAccessFile(url,"rw");
            fileChannel = raf.getChannel();
            try {
                fileLock = fileChannel.tryLock();
                byte[] buf = new byte[1024];
                while((raf.read(buf))!=-1){
                    String str = new String(buf,"utf-8");
                    if (StringUtils.isNotBlank(str)){
                        sb.append(str.replaceAll("\\u0000",""));
                    }
                    buf = new byte[1024];
                }
                list = Arrays.asList(sb.toString().split("\\n"));
            }catch (Exception e){
                e.printStackTrace();
                log.error("有其他线程正在操作该文件【"+url+"】，当前线程"+Thread.currentThread().getName());
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            closeAll( fileChannel, tempFileChannel, fileLock, raf);
            delFile(file1,isCopy,sqlFileUrl);
        }
        return list;
    }


    public void getFileData(List<String> fileStrList, String sqlFileUrl,String sqlFileName,String type,Long fileSize,Boolean isCopy){
        File file = new File(sqlFileUrl);
        if (!file.exists()){
            return ;
        }
        File[] files = file.listFiles();
        if (files.length == 0){
            return ;
        }

        List<File> tempFileList = new ArrayList<>();
        for (File f : files) {
            if (f.isDirectory()||
                !f.getName().split("_")[0].equals(type)||
                !f.getName().split("_")[1].equals(sqlFileName)){
                continue;
            }
            if (f.length() > 0){
                tempFileList.add(f);
            }
            if (tempFileList.size() >= fileSize.intValue()){
                break;
            }
        }
        for (File file1 : tempFileList) {
            if (!file1.exists()){
                continue;
            }
            String url = file1.getAbsolutePath();
            List<String> list = read(url,true,file1,sqlFileUrl);
            log.info("----------"+list);
            if(!list.isEmpty()){
                fileStrList.addAll(list);
            }
        }
    }
    @Async
    public void delFile(File file1,Boolean isCopy,String sqlFileUrl){
        try{
            if (file1.exists()){
                if(isCopy){
                    copyFile(file1,sqlFileUrl + "\\delete\\",file1.getName());
                }
                FileUtil.del(file1.getAbsolutePath());
            }
        }catch (Exception exception){
            exception.printStackTrace();
        }
    }

    /**
     *
     * @param file
     * @param de
     * @param deName
     */
    public  void copyFile(File file,String de,String deName){
        try{
            File tempFile = new File(de);
            de += UUID.fastUUID().toString(true) + "_" + deName;
            if (!tempFile.exists()){
                tempFile.mkdir();
            }
            FileUtil.copy(file.getAbsolutePath(),de, false);
        }catch (Exception exception){
            exception.printStackTrace();
        }

    }

    private  void closeAll( FileChannel fileChannel,FileChannel tempFileChannel,FileLock fileLock,RandomAccessFile raf){
        if (fileLock != null) {
            try {
                fileLock.release();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (raf != null) {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (fileChannel != null) {
            try {
                fileChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (tempFileChannel != null) {
            try {
                tempFileChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
